package com.furentech.iotserver.fa.server.handler;


import com.furentech.iotserver.fa.mqtt.MqttPublisher;
import com.furentech.iotserver.fa.server.ChannelUtil;
import com.furentech.iotserver.fa.sinopec.SinopecCRCUtil;
import com.furentech.iotserver.fa.sinopec.SinopecPackageProcessor;
import com.furentech.iotserver.fa.sinopec.SinopecParam;
import com.furentech.iotserver.fa.utils.*;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;


public class SinopecHandler extends SimpleChannelInboundHandler<byte[]> {

    private final static Logger logger = LoggerFactory.getLogger(SinopecHandler.class);



    @Override
    protected void channelRead0(ChannelHandlerContext ctx, byte[] bytesFromLastChannel) throws Exception {


        int sourceAddr=bytesFromLastChannel[0]&0x00ff;


        //0-0xFA
        //1-destination addr
        //2-source addr

        // if  FA E0 E0 is not contained
        //3-frame num                   0
        //4-5  length of payload data   1-2
        //6-6+length   payload data     3-3+length

        //set the frameNumber of this channel
        ChannelUtil.setChannelFrameNumber(ctx.channel(),bytesFromLastChannel[1]);

        //calculate validDataLength from the corresponding package field
        Integer validDataLength=0;

        validDataLength+= BCD8421Operater.bcd2decimal(bytesFromLastChannel[2]);
        validDataLength*=100;
        validDataLength+=BCD8421Operater.bcd2decimal(bytesFromLastChannel[3]);


        /**     1Byte   1Byte   1Byte   1Byte           2Bytes      N bytes     2byte
         *      0xFA    desti   source  frameNum     dataLength     data        crc16
         */

        if(bytesFromLastChannel.length!=validDataLength+6)
        {
            logger.warn(String.format("数据长度错误，计算出：%d,实际:%d",validDataLength,bytesFromLastChannel.length-6));
            return;
        }

        byte[] validDataBuf=new byte[validDataLength] ;

        for(int i=0;i<validDataLength;i++)
        {
            validDataBuf[i]=bytesFromLastChannel[i+4];
        }

        //get param from spring config file
        SinopecParam sinopecParam=(SinopecParam)SpringUtil.getBean(SinopecParam.class);

        //crc is caculated from desti(Byte1) to the end of valid
        int crc= SinopecCRCUtil.calcCrc16WithAddr(sinopecParam.destiAddr,sourceAddr,bytesFromLastChannel,1,bytesFromLastChannel.length-3);

        if((crc&0x00ff)!=(0x00ff&bytesFromLastChannel[bytesFromLastChannel.length-1]))
        {
            logger.warn("crc计算结果低8位与接收到的不一致");
            return;
        }

        if(((crc>>8)&0x00ff)!=(0x00ff&bytesFromLastChannel[bytesFromLastChannel.length-2]))
        {
            logger.warn("crc计算结果高8位与接收到的不一致");
            return;
        }

        /**
         * 根据配置文件设置该通道对应的设备sourceAddr
         */
        ChannelUtil.setChannelDevSourceAddr(ctx.channel(), (byte) (sinopecParam.devSourceAddr&0x00ff));

        //we have got a valid data package from fcc device

        ChannelUtil.setCurrentChannel(ctx.channel());


        byte[] dataBufWithFrameNum=new byte[validDataBuf.length+3];

        System.arraycopy(bytesFromLastChannel,1,dataBufWithFrameNum,0,dataBufWithFrameNum.length);
        //process
        SinopecPackageProcessor processor=(SinopecPackageProcessor)SpringUtil.getBean("sinopecPackageProcessor");

        String readableResString=processor.getReadableString(validDataBuf);


        MqttPublisher mqttPublisher=(MqttPublisher)SpringUtil.getBean("mqttPublisher");


        if(readableResString!=null)
        {
            System.out.printf(readableResString+"\r\n");
            String topicReadable=String.format("%s/%s/%02x",sinopecParam.readableMsgTopic,HexStringUtils.toHexString(validDataBuf, 0, 1),sinopecParam.devSourceAddr);
            mqttPublisher.sendToMqtt(readableResString,topicReadable);
        }

        String jsonResString = processor.getJsonString(validDataBuf);
        if(jsonResString!=null)
        {
            System.out.printf(jsonResString+"\r\n");
            String topicHistory=String.format("%s/%s/%02x",sinopecParam.persistentMsgTopic,HexStringUtils.toHexString(validDataBuf, 0, 1),sinopecParam.devSourceAddr);
            mqttPublisher.sendToMqtt(jsonResString, topicHistory);
        }


        byte[] responseBuf = processor.getResponse(validDataBuf,ctx.channel());
        if(responseBuf!=null)
        {
            ctx.channel().writeAndFlush(responseBuf);
        }
    }
}
